// https://www.bilibili.com/video/BV1gL411Y7Mf/?spm_id_from=333.788&vd_source=716cc83db773dc676160781bc040d2f7
// 常用的12中工具类型
function get(url:string, ...rest: string[]) {
  return fetch(url).then(rsp => rsp.json() as Promise<{ ok: boolean }>)
}

type GetFunc = typeof get // 定义一个GetFunc的函数类型，结果是上面的get函数

type Param = Parameters<GetFunc> // 获取函数的参数类型，返回的是一个元组

type Return = ReturnType<GetFunc> // 获取函数的返回值

type Data = Awaited<Return> // 获取Promise中的结果类型

type Options = Readonly<{
  method?: 'GET' | 'POST',
  url: string,
  data?:any
}>

// Pick从Type中选择一个或多个属性，并返回一个新的类型
// Required 将Type中的所有属性设置为必选属性，并且返回一个新的类型
let defaultOptions: Required<Pick<Options, 'method'>> = { method: 'GET' } 

let defaultOptions2: Required<Omit<Options, 'url' | 'data'>> = { method: 'GET'} // Omit删除了属性url和data 
function mergeOptions(options: Options) {
  Options.method = 'GET' // Readonly 不允许修改
  return { ...defaultOptions, ...options}
}

// 定义一个国际化的实例的字段
type Language = 'zh' | 'en' | 'jp'
type Trans = { you: string, and: string, me: string }

// type I18n = {
//   zh: Trans;
//   en: Trans;
//   jp: Trans;
// }
// 以下代码得到上面的这种类型, Record 新建一个由keys指定的属性设置为只读属性和Type制定的值组成的对象类型
type I18n = Record<Language, Trans>

// 修改某个对象的属性值
interface Todo {
  id: number,
  title: string,
  desc: string
}
function updateTodo(todo: Todo, filedsToUpdate: Partial<Todo>) {
  return { ...todo, ...filedsToUpdate}
}

updateTodo({ id: 1, title: 'a', desc: 'b' }, { title: 'c'})

type Topics = 'js' | 'css' | 'html' | 'typescript' | 'go' | 'rust'

type FeTopics = Exclude<Topics, 'go' | 'rust' | 'c#'> // 从联合类型中排出一些类型
type BeTopics = Extract<Topics, 'go' | 'rust' | 'c#'> // 从联合类型中提取出一些类型

type T0 = string | number | undefined | null

type T1 = NonNullable<T0> // NonNullable 从Type中排出null和undefined类型，并返回一个新的类型